Jackson 2.x 系列【22】自定义序列化/反序列化器 您所在的位置:网站首页 qt 对象序列化 Jackson 2.x 系列【22】自定义序列化/反序列化器

Jackson 2.x 系列【22】自定义序列化/反序列化器

2024-06-17 05:31| 来源: 网络整理| 查看: 265

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

源码地址:https://gitee.com/pearl-organization/study-jaskson-demo

文章目录 1. 前言2. 案例演示2.1 序列化器2.2 反序列化器 3. 使用方式3.1 注解3.2 模块3.3 修饰器

1. 前言

在实际开发中,Jackson核心模块支持了常见类型的数据转换,此外还有很多第三方模块支持不常用的类型,基本已经够用。但是在某些特殊场景下,可能需要支持自定义类型或者转换规则。

2. 案例演示

演示需求:

后端查询的角色列表是一个字符串集合,需要反序列化为逗号分割的字符串,用于前端直接展示前端提交的是逗号分割的字符串,需要反序列化为集合

Java Bean如下:

public class UserVO { Long id; String username; List roleList; // 省略............. }

使用hutool工具类:

cn.hutool hutool-all 5.8.26 2.1 序列化器

自定义序列化器,之前有说过需要继承StdSerializer,而不是JsonSerializer,指定泛型为被序列化的数据类型List,实现序列化方法,集合为空时写入空字符串“”,不为空时转为逗号拼接的字符串:

public class ListToStringJsonSerializer extends StdSerializer { public static final ListToStringJsonSerializer instance = new ListToStringJsonSerializer(); public ListToStringJsonSerializer() { super(String.class, false); } /** * 序列化 * * @param value 被序列化的值 * @param jsonGenerator 生成器 * @param serializerProvider 提供者 * @throws IOException */ @Override public void serialize(List value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { // 空集合值写入 “” if (CollUtil.isEmpty(value)) { jsonGenerator.writeString(""); } else { // 写入转为“,”拼接的字符串 String commaString = CollUtil.join(value, StrUtil.COMMA); jsonGenerator.writeString(commaString); } } public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException { this.visitStringFormat(visitor, typeHint); } } 2.2 反序列化器

自定义反序列化器继承StdDeserializer,指定泛型反序列化后的数据类型List,实现反序列化方法。

当解析读取到的JsonToken时,需要处理以下几种情况:

JsonToken为null,返回空集合字符串为空,返回空集合字符串不为空,用逗号分割为集合返回 public class ListToStringJsonDeserializer extends StdDeserializer { public static final ListToStringJsonDeserializer instance = new ListToStringJsonDeserializer(); public ListToStringJsonDeserializer() { super(String.class); } /** * 反序列化 * * @param jsonParser 解析器 * @param deserializationContext 上下文 * @return 反序列化后的值 * @throws IOException */ @Override public List deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { if (jsonParser.hasToken(JsonToken.VALUE_NULL)) { // null 返回空集合 return new ArrayList(); } else if (jsonParser.hasToken(JsonToken.VALUE_STRING)) { // 当前是String类型 String textValue = jsonParser.getText();// 原值 // 空值返回空集合 if (textValue.isEmpty() || _isBlank(textValue)) { return new ArrayList(); } // “,”分割,返回集合 return StrUtil.split(textValue, StrUtil.COMMA, true, true); } throw JsonMappingException.from(jsonParser, "JSON有误"); } public LogicalType logicalType() { return LogicalType.Textual; } public boolean isCachable() { return true; } public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { return ""; } public List deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { return this.deserialize(p, ctxt); } } 3. 使用方式

定义好了序列化/反序列化器后,Jackson支持多种方式添加它们到执行过程中。

3.1 注解

使用@JsonSerialize、@JsonDeserialize指定序列化/反序列化器,这种方式粒度最细,优先级最高。

@JsonSerialize(using = ListToStringJsonSerializer.class) @JsonDeserialize(using = ListToStringJsonDeserializer.class) List roleList;

测试代码:

ObjectMapper objectMapper = new ObjectMapper(); UserVO userVO = new UserVO(); userVO.setId(1699657986705854464L); userVO.setUsername("jack"); List roleList=new ArrayList(); roleList.add("管理员"); roleList.add("经理"); userVO.setRoleList(roleList); // 序列化 String userVoJson = objectMapper.writeValueAsString(userVO); System.out.println(userVoJson); // 反序列化 String json="{\"id\":1699657986705854464,\"username\":\"jack\",\"roleList\":\"管理员,经理\"}"; UserVO readValue = objectMapper.readValue(json, UserVO.class); System.out.println(readValue);

输出结果:

{"id":1699657986705854464,"username":"jack","roleList":"管理员,经理"} UserVO{id=1699657986705854464, username='jack', roleList=[管理员, 经理]}

还可以使用组合注解的方式,更加方便:

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonSerialize(using = ListToStringJsonSerializer.class) @JsonDeserialize(using = ListToStringJsonDeserializer.class) public @interface JsonListToCommaSplitString { } @JsonListToCommaSplitString List roleList; 3.2 模块

在自定义模块中,也可以注册自定义序列化/反序列化器,但是这样作用的是全局对象,这里不太合适:

SimpleModule customModule = new SimpleModule(); // 自定义模块 // 注册自定义的序列化器/反序列化器 customModule.addSerializer(List.class,ListToStringJsonSerializer.instance); customModule.addDeserializer(List.class, ListToStringJsonDeserializer.instance); objectMapper.registerModule(customModule); // 注册自定义模块 3.3 修饰器

使用Java Bean序列化/反序列化修饰器提供的钩子方法,替换集合类型的序列化/反序列化器,作用于全局的Java Bean,这里不太合适。

public class ListToStringBeanSerializerModifier extends BeanSerializerModifier { public JsonSerializer modifyCollectionSerializer(SerializationConfig config, CollectionType valueType, BeanDescription beanDesc, JsonSerializer serializer) { return ListToStringJsonSerializer.instance; } } public class ListToStringBeanBeanDeserializerModifier extends BeanDeserializerModifier { public JsonDeserializer modifyCollectionDeserializer(DeserializationConfig config, CollectionType type, BeanDescription beanDesc, JsonDeserializer deserializer) { return ListToStringJsonDeserializer.instance; } }

使用模块注册:

// 使用模块注册BeanModifier: SimpleModule simpleModule=new SimpleModule("myModule"); simpleModule.setSerializerModifier(new ListToStringBeanSerializerModifier()); simpleModule.setDeserializerModifier(new ListToStringBeanBeanDeserializerModifier()); objectMapper.registerModule(simpleModule);// 注册模块


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有